<?php

namespace App\Services\Tools;

use App\Enums\ChatEnum;
use App\Enums\RedisKeyEnum;
use App\Exceptions\BasicException;
use Illuminate\Support\Facades\Log;
use App\Jobs\RongCloud\BroadcastPushJob;
use App\Jobs\RongCloud\RoomPushJob;
use App\Jobs\RongCloud\UserPushJob;
use RongCloud\RongCloud;

class RongCloudService
{

    public function __construct()
    {
        $this->client = new RongCloud(config('rongcloud.app_key'), config('rongcloud.app_secret'));
    }

    /**
     * 异步队列推送
     * @param $senderId
     * @param $targetId
     * @param $content
     * @param int $delay
     */
    public function queue($senderId, $targetId, $content, $delay = 0, $type = 'RC:CmdMsg')
    {
        if ($this->isRoom($targetId)) {
            $job = new RoomPushJob($senderId, $targetId, $content, $type);
            dispatch($job->delay($delay));
        } else if ($this->isUser($targetId)) {
            $job = new UserPushJob($senderId, $targetId, $content, $type);
            dispatch($job->delay($delay));
        } else if ($this->isBroadcast($targetId)) {
            $job = new BroadcastPushJob($senderId, $content, $type);
            dispatch($job->delay($delay));
        }
    }

    /**
     * 自适应同步推送
     * @param $senderId
     * @param $targetId
     * @param $content
     * @return array
     */
    public function push($senderId, $targetId, $content, $type = 'RC:CmdMsg')
    {
        $result = [];
        if ($this->isRoom($targetId)) {
            $result = $this->roomPush($senderId, $targetId, $content, $type);
        } else if ($this->isUser($targetId)) {
            $result = $this->userPush($senderId, $targetId, $content, $type);
        } else if ($this->isBroadcast($targetId)) {
            $result = $this->broadcastPush($senderId, $content, $type);
        }
        return $result;
    }

    /**
     * 房间同步推送
     * @param $senderId
     * @param $targetId
     * @param $content
     * @return array
     */
    public function roomPush($senderId, $targetId, $content, $type = 'RC:CmdMsg')
    {
        $result = $this->client->getMessage()->Chatroom()->send([
            'senderId' => $senderId,
            'targetId' => $targetId,
            'objectName' => $type,
            'content' => json_encode($content),
        ]);

        return $result;
    }

    /**
     * 用户同步推送
     * @param $senderId
     * @param $targetId
     * @param $content
     * @return array
     */
    public function userPush($senderId, $targetId, $content, $type = 'RC:CmdMsg')
    {
        $message = [
            'senderId' => $senderId,
            'targetId' => $targetId,
            'objectName' => $type,
            'content' => json_encode($content),
        ];
        $result = $this->client->getMessage()->Person()->send($message);

        return $result;
    }

    /**
     * 全局同步推送
     * @param $senderId
     * @param $content
     * @return array
     */
    public function broadcastPush($senderId, $content, $type = 'RC:CmdMsg')
    {
        $result = $this->client->getMessage()->Chatroom()->broadcast([
            'senderId' => $senderId,
            'objectName' => $type,
            'content' => json_encode($content),
        ]);

        return $result;
    }

    public function isRoom($topic)
    {
        $prefix = substr($topic, 0, 5);
        if ($prefix === 'room_' || $prefix === 'theme') {
            return true;
        }
        return false;
    }

    public function isUser($topic)
    {
        if (substr($topic, 0, 5) === 'user_') {
            return true;
        }
        return false;
    }

    public function isBroadcast($topic)
    {
        if ($topic === 'room') {
            return true;
        }
        return false;
    }

    public function getRoomName($roomId)
    {
        return 'room_' . $roomId;
    }

    public function getUserName($userId)
    {
        return 'user_' . $userId;
    }

    public function getBroadcast()
    {
        return 'room';
    }

    /**
     * 创建用户获取 Token
     * @param $userId
     * @param $name
     * @param string $avatar
     * @return array
     */
    public function createUser($userId, $name, $avatar = 'https://')
    {
        $user = [
            'id' => 'user_' . $userId,
            'name' => $name,//用户名称
            'portrait' => $avatar //用户头像
        ];
        $result = $this->client->getUser()->register($user);
        return $result;
    }

    /**
     * 创建房间
     * @param $id
     * @param $name
     * @return mixed|null
     */
    public function createRoom($room_id, $name)
    {
        return $this->client->getChatroom()->create([
            'id' => $room_id,
            'name' => $name,
        ]);
    }

    /**
     * 销毁房间
     * @param $roomId
     */
    public function destroyRoom($roomId)
    {
        $result = $this->client->getChatroom()->destory([
            'id' => 'room_' . $roomId,
        ]);
        return $result;
    }

    /**
     * 获取房间信息
     * @param $roomId
     * @return mixed|null
     */
    public function getRoom($roomId)
    {
        $result = $this->client->getChatroom()->get([
            'id' => 'room_' . $roomId,
        ]);
        return $result;
    }

    /**
     * 获取历史消息
     */
    public function getHistoryChatLog($date="",$isCheck=true)
    {
        $date = "2021062114";
        if(empty($date)){
            $timestamp = strtotime("-1 hour");
            $date = date('YmdH', $timestamp);
        }
        //解压后的文件名
        $unzipFilename = date('Y-m-d-H',strtotime($date));
        //文件保存路径
        $path = storage_path('logs/chat');
       
        if($isCheck){
            $result = $this->client->getMessage()->History()->get(['date'=> $date]);
            if($result['code'] == 200){
                $zipPath = $result['url'];
                if(!file_exists($path)){
                    mkdir($path,0777,true);
                }
                //下载zip文件到本地
                $bool = $this->downloadFile($zipPath, $path, $unzipFilename);
                if (!$bool) return ['status' => 0, 'msg' => '文件下载失败'];

                //解压文件
                $bool = $this->unzip($unzipFilename . '.zip', $path);
                if (!$bool) return ['status' => 0, 'msg' => '文件解压失败'];

                //获取数据
                $data = [];
                $this->getData($path . $unzipFilename, $data);
                return ['status' => 1, 'msg' => '获取成功', 'data' => $data];
            }
        }
        die;
        
    }

    /**
     * 下载文件
     * @param string $downloadUrl 下载链接
     * @param string $path 文件保存路径
     * @param string $filename 文件保存名称
     * @return int|false
     */
    private function downloadFile($downloadUrl, $path, $filename)
    {
        return file_put_contents($path . $filename . '.zip', file_get_contents($downloadUrl));
    }

    /**
     * 解压zip
     * @param string $filename 要解压的文件名
     * @param string $path 要解压的文件所在路径，同时也是解压后文件的保存路径
     * @return bool
     */
    private function unzip($filename, $path) {
        $zip = new \ZipArchive();

        if (empty($filename) || empty($path)) {
            return false;
        }

        if ($zip->open($path . $filename) === true) {
            $zip->extractTo($path);
            $zip->close();
            //解压完成删除zip文件
            unlink($path . $filename);
            return true;
        } else {
            return false;
        }
    }

    //从文件中获取数据
    private function getData($file, &$data)
    {
        $data = file_get_contents($file);
        $data = explode("\r\n", $data);
        foreach ($data as $k => &$v) {
            if ($v) $v = json_decode(substr($v, 19), true);
            else unset($data[$k]);
        }
    }

    public function getUserInfo($userId,$url){
        $params = [
            'userId' => 'user_'.$userId
        ];
        $headerParam = $this->getRySign();
        $ch         = curl_init();
        curl_setopt($ch, CURLOPT_POSTFIELDS, $this->build_query($params));
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headerParam);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //处理http证书问题
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_USERAGENT, "rc-php-sdk/3.0.12");
        //        curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $ret = curl_exec($ch);
        if (false === $ret) {
            $ret = curl_errno($ch);
            $res = ['code'=>curl_errno($ch),'msg'=>curl_error($ch)];
            return $res;
        }
        curl_close($ch);
        $result = json_decode($ret, true);
        return  empty($result)?[]:$result;
    }
    private function build_query($formData, $numericPrefix = '', $argSeparator = '&', $prefixKey = '') {
        $str = '';
        foreach ($formData as $key => $val) {
            if (!is_array($val)) {
                $str .= $argSeparator;
                if ($prefixKey === '') {
                    if (is_int($key)) {
                        $str .= $numericPrefix;
                    }
                    $str .= urlencode($key) . '=' . urlencode($val);
                } else {
                    $str .= urlencode($prefixKey) . '=' . urlencode($val);
                }
            } else {
                if ($prefixKey == '') {
                    $prefixKey .= $key;
                }
                if (isset($val[0]) && is_array($val[0])) {
                    $arr       = array();
                    $arr[$key] = $val[0];
                    $str       .= $argSeparator . http_build_query($arr);
                } else {
                    $str .= $argSeparator . $this->build_query($val, $numericPrefix, $argSeparator, $prefixKey);
                }
                $prefixKey = '';
            }
        }
        return substr($str, strlen($argSeparator));
    }


    public function getRySign(){
        // 重置随机数种子。
        srand((double)microtime()*1000000);

        $appSecret = env('RONGCLOUD_APP_SECRET'); // 开发者平台分配的 App Secret。
        $nonce = rand(); // 获取随机数。
        $timestamp = time()*1000; // 获取时间戳（毫秒）。
        $signature = sha1($appSecret.$nonce.$timestamp);
        return [
            'RC-App-Key:'.env('RONGCLOUD_APP_KEY'),
            'RC-Nonce:'.$nonce,
            'RC-Timestamp:' .$timestamp,
            'RC-Signature:' .$signature,
            "Content-Type:application/x-www-form-urlencoded"
        ];
    }

    /**
     * @Desc:家族推送,不走队列
     * @param $senderId
     * @param $targetId
     * @param $content
     * @param $type
     * @return array
     * @author: shiquan
     * @Time: 2022/12/7 10:12
     */
    public function pushFamily($senderId, $targetId, $data, $pushType,  $type = 'qh:familyGroup')
    {
        $uniKey = $this->uniqidReal();
        $content = [
            'extra'     => $data,
            'type'    => $pushType,
            'time'    => $this->getMillisecond(),
            'uni_key' => $uniKey,
        ];
        $result = $this->familyPush($senderId, $targetId, $content, $type);

        return $result;
    }

    function getMillisecond()
    {
        [$s1, $s2] = explode(' ', microtime());

        return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
    }

    function uniqidReal($lenght = 13)
    {
        // uniqid gives 13 chars, but you could adjust it to your needs.
        if (function_exists("random_bytes")) {
            $bytes = random_bytes(ceil($lenght / 2));
        } elseif (function_exists("openssl_random_pseudo_bytes")) {
            $bytes = openssl_random_pseudo_bytes(ceil($lenght / 2));
        } else {
            return uniqid();
        }

        return substr(bin2hex($bytes), 0, $lenght);
    }

    /**
     * @Desc:家族推送
     * @param $senderId
     * @param $targetId
     * @param $content
     * @param $type
     * @return array
     * @author: shiquan
     * @Time: 2022/12/7 14:56
     */
    public function familyPush($senderId, $targetId, $content, $type = 'qh:familyGroup')
    {
        $result = $this->client->getMessage()->Group()->send([
            'senderId'   => 'system',
            'targetId'   => $targetId,
            'objectName' => $type,
            'content'    => json_encode($content),
        ]);
        Log::info('推送返回结果:'.json_encode($result, JSON_UNESCAPED_UNICODE));
        return $result;
    }

    /**
     * @Desc:解散融云群组
     * @param $familyId
     * @param $userId
     * @return array
     * @author: shiquan
     * @Time: 2022/12/13 17:50
     */
    public function dissolveRyFamily($familyId, $userId)
    {
        $data = [
            'id'=> 'family_'.$familyId,             //群组 id
            'member'=> ['id'=> 'user_'.$userId],    //群成员信息
        ];
        $res = $this->client->getGroup()->dismiss($data);
        if ($res['code'] != 200) {
            return false;
        }

        return $data['id'];
    }
}
